retour\alloc/
mod.rs

1use crate::error::Result;
2use std::ops::{Deref, DerefMut};
3use std::sync::{Arc, Mutex};
4
5mod proximity;
6mod search;
7
8/// A thread-safe memory pool for allocating chunks close to addresses.
9pub struct ThreadAllocator(Arc<Mutex<proximity::ProximityAllocator>>);
10
11// TODO: Decrease use of mutexes
12impl ThreadAllocator {
13  /// Creates a new proximity memory allocator.
14  pub fn new(max_distance: usize) -> Self {
15    ThreadAllocator(Arc::new(Mutex::new(proximity::ProximityAllocator {
16      max_distance,
17      pools: Vec::new(),
18    })))
19  }
20
21  /// Allocates read-, write- & executable memory close to `origin`.
22  pub fn allocate(&self, origin: *const (), size: usize) -> Result<ExecutableMemory> {
23    let mut allocator = self.0.lock().unwrap();
24    allocator
25      .allocate(origin, size)
26      .map(|data| ExecutableMemory {
27        allocator: self.0.clone(),
28        data,
29      })
30  }
31}
32
33/// A handle for allocated proximity memory.
34pub struct ExecutableMemory {
35  allocator: Arc<Mutex<proximity::ProximityAllocator>>,
36  data: proximity::Allocation,
37}
38
39impl Drop for ExecutableMemory {
40  fn drop(&mut self) {
41    // Release the associated memory map (if unique)
42    self.allocator.lock().unwrap().release(&self.data);
43  }
44}
45
46impl Deref for ExecutableMemory {
47  type Target = [u8];
48
49  fn deref(&self) -> &Self::Target {
50    self.data.deref()
51  }
52}
53
54impl DerefMut for ExecutableMemory {
55  fn deref_mut(&mut self) -> &mut [u8] {
56    self.data.deref_mut()
57  }
58}